package com.ebupt.migu.music.schedule;

import com.ebupt.migu.common.pojo.StatusRequestBean;
import com.ebupt.migu.music.common.constants.UserGroupConstants;
import com.ebupt.migu.music.common.entity.UserGroupInfo;
import com.ebupt.migu.music.common.utils.ESearch;
import com.ebupt.migu.music.common.utils.FileRW;
import com.ebupt.migu.music.common.utils.UpdateUserGroupSize;
import com.ebupt.migu.music.redis.service.RedisService;
import com.ebupt.migu.music.userGroup.mapper.NewCrowdMapper;
import com.ebupt.migu.restapi.DownloadByFtp;
import com.ebupt.migu.restapi.RestHttpPost;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;

/**
 * 音乐侧客群分箱执行任务类
 *
 * @author lemon
 * @since 2022-08-22 17:03
 */
@Slf4j
@EnableScheduling
@Component
public class SplitGroupTask {

    @Resource
    private ESearch eSearch;
    @Resource
    private RedisService redisService;
    @Resource
    private UpdateUserGroupSize updateUserGroupSize;
    @Resource
    private NewCrowdMapper newCrowdMapper;
    @Value("${label.prefix}")
    private String labelPrefix;
    @Value("${label.post_url}")
    private String postUrl;
    @Value("${label.customer_status}")
    private String customerStatus;

    /**
     * 自动获取待更新的分箱客群，并更新信息
     */
    @Async("taskExecutor")
    @Scheduled(cron = "${cron.splitGroup}")
    public void splitGroup() {
        // 查询待更新的分箱人群
        List<UserGroupInfo> groupInfos = newCrowdMapper.querySplitGroups();
        if (groupInfos == null || groupInfos.size() <= 0) {
            log.info("当前无待更新的分箱人群");
            return;
        }
        // 取第一个待分箱的客群进行分箱
        UserGroupInfo userGroupInfo = groupInfos.get(0);
        String groupId = userGroupInfo.getGroupId();
        log.info("分箱人群ID:{}", groupId);
        // 更新人群状态至更新中
        Map<String, Object> params = new HashMap<>(1);
        params.put("createStatus", UserGroupConstants.UPDATING);
        params.put("groupId", groupId);
        newCrowdMapper.updateCrowd(params);
        // 获取客群手机号信息
        File phoneFile = DownloadByFtp.getLabelUserGroupForGPush(groupId, "splitGroup", labelPrefix + postUrl, 1, userGroupInfo.getCreatorName());
        log.info("文件路径:{}", phoneFile);
        // 读取文件内容
        List<String> contents = FileRW.getContent(phoneFile);
        if (null == contents || contents.size() == 0) {
            params.clear();
            params.put("groupId", groupId);
            params.put("createStatus", UserGroupConstants.IMPORT_FAILED);
            params.put("remark", "文件内容异常");
            log.info("文件内容异常:{}", phoneFile);
            newCrowdMapper.updateCrowd(params);
            // 更新使用该人群的待进行策略信息
            updateStrategyInfo(groupId);
            return;
        }
        saveToRedis(groupId, contents);
        updateUserGroupSize.update(groupId, 1, 0);
        // 通知tsg删除分箱文件(调用客群状态通知接口)
        StatusRequestBean statusRequestBean = new StatusRequestBean(groupId, 9);
        log.info("通知tsg删除分箱文件：{}", statusRequestBean);
        new RestHttpPost().doRest(statusRequestBean, labelPrefix + customerStatus);
        log.info("更新完成，分箱人群ID：{}", groupId);
    }

    /**
     * 读取文件内容，并反查出数据存入redis
     *
     * @param groupId  客群id
     * @param contents 文件内容
     */
    private void saveToRedis(String groupId, List<String> contents) {
        // redis key
        String phoneKey = groupId + "-phone", imeiKey = groupId + "-imei", uidKey = groupId + "-uid";
        // 建立redis连接
        BoundSetOperations<String, String> phoneBound = redisService.unlinkAndGetConnect(phoneKey, 0);
        BoundSetOperations<String, String> imeiBound = redisService.unlinkAndGetConnect(imeiKey, 0);
        BoundSetOperations<String, String> uidBound = redisService.unlinkAndGetConnect(uidKey, 0);
        Map<String, Object> result;
        //  结果集
        Set<String> uidSet = new HashSet<>();
        Set<String> imeiSet = new HashSet<>();
        Set<String> msisdnSet = new HashSet<>();
        for (String content : contents) {
            // 去除空文件
            if (StringUtils.isEmpty(content)) {
                continue;
            }
            result = eSearch.analysis2(content, "1", "0", null, null, null, null);
            if (null == result) {
                continue;
            }
            // 反查结果
            if (null != result.get("uids")) {
                uidSet = (Set<String>) result.get("uids");
            }
            if (null != result.get("imeis")) {
                imeiSet = (Set<String>) result.get("imeis");
            }
            if (null != result.get("msisdns")) {
                msisdnSet = (Set<String>) result.get("msisdns");
            }

            // 结果添加到redis的值中
            if (null != uidSet && uidSet.size() != 0) {
                for (String uid : uidSet) {
                    uidBound.add(uid.trim());
                }
            }
            if (null != imeiSet && imeiSet.size() != 0) {
                for (String imei : imeiSet) {
                    if (!"00000000-0000-0000-0000-000000000000".equals(imei.trim())) {
                        imeiBound.add(imei.trim());
                    }
                }
            }
            if (null != msisdnSet && msisdnSet.size() != 0) {
                for (String msisdn : msisdnSet) {
                    phoneBound.add(msisdn.trim());
                }
            }
        }
    }

    /**
     * 人群创建失败时，更新待使用的策略信息
     *
     * @param groupId 人群id
     */
    private void updateStrategyInfo(String groupId) {
        // 人群创建失败，查询待使用的策略是否引用该人群，修改策略状态
        FTPGroupTask.updateStrategy(groupId, newCrowdMapper, log);
    }
}
